import datetime
import re

from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View

# from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango123.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango123.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid
from myapp.models import *
from django.utils.deprecation import MiddlewareMixin
from myapp.serializers import CarouselSer

# 添加轮播图
class add_Carousel(APIView):
    def post(self,request):
        name=request.POST.get('name')
        src=request.POST.get('src')
        img=request.POST.get('img')
        carousel_obj=Carousel.objects.filter(name=name).first()
        if carousel_obj:
            return Response({"code": 403, 'msg': '已存在'})
        try:
            my_carousel=Carousel(name=name,src=src,img=img)
            my_carousel.save()
        except Exception as e:
            return Response({"code": 403, 'msg': '添加失败'})
        return Response({"code": 200, 'msg': '添加成功'})

#轮播图后台接口
class GetCarousel(APIView):

    def get(self,request):
        # 读库
        carousels = Carousel.objects.all()
        # 序列化操作
        carousels_ser= CarouselSer(carousels,many=True)
        return Response(carousels_ser.data)

    def delete(self,request):
        id=request.GET.get('id')
        mycarousel = Carousel.objects.get(pk=id)
        mycarousel.delete()
        return Response({"code": 200, 'msg': '删除成功'})

    def post(self,request):
        id=request.POST.get('id')
        name=request.POST.get('name')
        src=request.POST.get('src')
        img=request.POST.get('img')
        mycarousel=Carousel.objects.get(pk=id)
        # 更改保存
        mycarousel.name=name
        mycarousel.src=src
        mycarousel.img=img
        mycarousel.save()
        return Response({"code":200,'msg':'修改成功'})
#自定义中间件
class MyMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('过滤中间件')
        # 获取路由
        if request.path_info.startswith('/myapp/upload/'):
            return JsonResponse({'msg':"您篡改了中间件"},safe=False,json_dumps_params={"ensure_ascii":False})
        # return HttpResponse(json.dumps({'msg':"您篡改了中间件"},ensure_ascii=False,indent=4),content_type='application/json')
        pass
    def process_view(self,request,view_func,view_args,view_kwargs):
        pass
    def process_exception(self,request,exception):
        pass
    def process_response(self,request,response):
        return response


r = redis.Redis('localhost', 6379)

from django.utils.decorators import method_decorator
# 定义权限检测装饰器
def my_decorator(func):
    def warpper(request,*args,**kwargs):
        uid=request.GET.get('uid',None)
        myjwt=request.GET.get('jwt',None)
        try:
            decode_jwt = jwt.decode(myjwt, '201528', algorithms=['HS256'])
        except Exception as e:
            return Response({'code': 401, 'msg': '您的秘钥已失效'})

        if int(uid)!= int(decode_jwt['data']['uid']):
            return Response({'code':401,'msg':'您的秘钥无权限'})
        return func(request,*args,**kwargs)
    return warpper

# 绑定手机
class Update_Phone(APIView):
    def get(self,request):
        uid = request.GET.get('uid')
        user = User.objects.filter(pk=uid).first()
        return JsonResponse({'code': 200,'phone': user.phone})

    def post(self,request):
        uid=request.POST.get('uid')
        phone=request.POST.get('phone',None)
        if phone is None:
            return JsonResponse({'code': 403, 'msg': '手机号不正确'})
        user = User.objects.filter(pk=uid).first()
        user.phone=phone
        user.save()
        return Response({'code':200,'msg':'更改成功'})
# 又拍云
import  upyun
class UpYun(View):
    def get(self,request):
        uid = request.GET.get('uid')
        dirname = request.GET.get('dirname')
        up = upyun.UpYun('mdsave', username='ljq', password='m3QsiAaLhMvB8owYEwdl1l2atviBVF3U')
        up.mkdir('/%s/'%dirname)

        return JsonResponse({'msg': '创建成功'})

    def post(self,request):
        # 获取图片
        img = request.FILES.get('file')
        uid=request.POST.get('uid',None)
        user=User.objects.filter(pk=uid).first()
        filename = make_password(img.name) + str((int(round(time.time() * 1000)))) + ".jpg"
        # 实例化对象
        up = upyun.UpYun('mdsave',username='ljq',password='m3QsiAaLhMvB8owYEwdl1l2atviBVF3U')
        # 删除原有图片
        if user.img != 'user.png':
            up.delete('./%s' % user.img)
        headers = { 'x-gmkerl-quality': '90' }
        # 分块上传
        for chunk in img.chunks():
            res = up.put('/%s'%filename,chunk,checksum=True,headers=headers)
        user.img=filename
        user.save()
        return JsonResponse({'filename':filename})

    def delete(self,request):
        uid=request.GET.get('uid')
        # 查询对象
        user = User.objects.filter(pk=uid).first()
        # 删除又拍云文件
        if user.img!='user.png':
            # 实例化upyun 对象
            up = upyun.UpYun('mdsave', username='ljq', password='m3QsiAaLhMvB8owYEwdl1l2atviBVF3U')
            up.delete('./%s'%user.img)
            # 修改数据库为默认头像
            user.img = 'user.png'
            user.save()
        return JsonResponse({'code':200,'msg': '删除成功'})

# 七牛token
from qiniu import  Auth
class Qiniu(APIView):
    def get(self,request):
        # 声明认证对象
        q = Auth(access_key='4CmF2Dy-Xi7PQwHm7Ovpk7YlOiw2pqzUqyf7ybhA',secret_key='y3tlCWWdvmgsm2a9j6Plu_WWM4b0jFRTD-f3bHZ7')
        # 获取token
        token=q.upload_token('md1907rgzn')
        return Response({'token':token})

    def post(self,request):
        uid=request.POST.get('uid',None)
        key=request.POST.get('key',None)
        user=User.objects.filter(pk=uid).first()
        user.img=key
        user.save()
        return Response({'code':200,'msg':'修改完成'})

# 加水印
def cn_logo(img_name):
    img = Image.open('.//static/upload/'+img_name)
    # 获取宽高
    width, height = img.size
    # 根据图片大小定义logo大小
    text = '美多商城'
    font = ImageFont.truetype('msyh.ttc', (width - height) // 10)
    # 获取字体宽高
    font_width, font_height = font.getsize(text)
    # 使用画笔
    draw = ImageDraw.Draw(img)
    # 写入文本
    draw.text((width - font_width, height - font_height - 10), text, (100, 100, 100), font=font)
    # 加密下文件名防止重复
    filename = make_password(img_name) + str((int(round(time.time() * 1000)))) + ".jpg"
    # 根据路径保存文件
    img.save(os.path.join(UPLOAD_ROOT, '', filename))
    os.remove('.//static/upload/' + img_name)  # 删除原图片
    return filename

# 文件上传通用类
class UploadFile(APIView):
    @method_decorator(my_decorator)
    def get(self,request):
        uid=request.GET.get('uid',None)
        user=User.objects.filter(pk=uid).first()
        if user.img:
            return Response({"code":200,'filename':user.img})
        else:
            return Response({"code":200,'filename':'user.png'})

    def post(self,request):
        myfile=request.FILES.get('file')
        uid=request.POST.get('uid')
        # 判断文件类型
        if not re.match('.*(jpg|png|jpeg)$', myfile.name):
            return Response({'code': 403,'msg':'请上传png或者jpg格式'})
        with open(os.path.join(UPLOAD_ROOT,'',myfile.name),'wb')as f:
            for chunk in myfile.chunks():
                f.write(chunk)
        # 调用水印函数
        filename=cn_logo(myfile.name)
        # 更改数据库
        try:
            user=User.objects.filter(pk=uid).first()
            if user.img:  # 删除旧图片
                os.remove('.//static/upload/'+user.img)
            user.img=filename
            user.save()
        except Exception as e:
            print(e)
            pass
        return Response({"code":200,"msg":"更改成功",'filename':filename})

class MyCode(View):
    # 定义rgb随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, G, B)

    # 定义图片视图
    def get(self, request):
        # 画布
        img_size = (120, 50)
        # 定义图片对象
        image = Image.new('RGB', img_size, 'white')
        # 定义画笔
        draw = ImageDraw.Draw(image, 'RGB')
        source = '0123456789abcdefghijk'
        # 接受容器
        code_str = ''
        # 进入循环绘制
        for i in range(4):
            # 获取字母颜色
            text_corlor = self.get_random_color()
            # 获取随机下标
            tmp_num = random.randrange(len(source))
            # 随机字符串
            random_str = source[tmp_num]
            # 装入容器
            code_str += random_str
            # 绘制字符串
            draw.text((10 + 30 * i, 20), random_str, text_corlor)
        # 获取缓存区
        buf = io.BytesIO()
        # 将临时图片保存到缓冲
        image.save(buf, 'png')
        # 保存验证码
        r.set('code', code_str)
        request.session['code'] = code_str
        # print(r.get('code'))
        return HttpResponse(buf.getvalue(), 'image/png')


def wb_back(request):
    code = request.GET.get('code', None)
    # 微博接口地址
    access_token_url = "https://api.weibo.com/oauth2/access_token"
    # 定义参数
    re = requests.post(access_token_url, data={
        "client_id": '2464168997',
        "client_secret": "e4d72c1377c3b5cf549ceeba59866090",
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": "http://127.0.0.1:8000/myapp/weibo",
    })
    # 获取用户信息
    res = requests.get('https://api.weibo.com/2/users/show.json',
                       params={"access_token": re.json()["access_token"], "uid": re.json()["uid"]})
    username = str(res.json()['name'])
    # 判断是否用新浪微博登录过
    user = User.objects.filter(username=username).first()
    sina_id = ''
    user_id = ''
    if user:
        # 代表曾经登录过
        sina_id = user.username
        user_id = user.id
    else:
        # 首次登陆
        User(username=username, password=make_password(res.json()['id'])).save()
        user = User.objects.filter(username=username).first()
        sina_id = user.username
        user_id = user.id

    print(sina_id, user_id)
    time.sleep(2)
    return redirect("http://localhost:8080?another_id=" + str(sina_id) + "&uid=" + str(user_id))


def ding_back(request):
    import hmac
    import urllib
    import base64
    from hashlib import sha256
    code = request.GET.get('code', None)
    t = time.time()
    # 时间戳/毫秒
    timestamp = str((int(round(t * 1000))))
    appSecret = "TExmhPpdl-HHMHyhYxuqcEAj4UWiz3gS0nvsc19ws4-euLXKsPUbEyhY_zLTFffu"
    # 构造签名
    signature =  base64.b64encode(hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=hashlib.sha256).digest())
    data={'tmp_auth_code': code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaax69jocuwkatfpfg",data=json.dumps(data),headers=headers)
    print(res.json())
    username=res.json()['user_info']['nick']
    # 判读是否是第一次
    user = User.objects.filter(username=username).first()
    ding_id = ''
    user_id = ''
    if user:
        # 代表曾经登录过
        ding_id = user.username
        user_id = user.id
    else:
        # 首次登陆
        User(username=username, password=make_password(res.json()['user_info']['openid'])).save()
        user = User.objects.filter(username=username).first()
        ding_id = user.username
        user_id = user.id

    print(ding_id, user_id)
    time.sleep(2)
    return redirect("http://localhost:8080?another_id=" + str(ding_id) + "&uid=" + str(user_id))


def make_password(mypass):
    # 生成MD5对象
    md5 = hashlib.md5()
    # 转码操作
    mypass_utf8 = str(mypass).encode(encoding="utf-8")
    # 加密操作
    md5.update(mypass_utf8)
    # 返回密文
    return md5.hexdigest()


class Login(APIView):
    def get(self, request):
        username = request.GET.get('username', None)
        password = request.GET.get('password', None)
        code = request.GET.get('code', None)

        # 判断验证码
        # print(request.session.get('code', None))
        if code != r.get('code').decode('utf-8'):
            print(request.session.get('code', None))
            return Response({"code": 403, "msg": "验证码错误"})
        # 判断是否有锁
        if r.exists("%s-lock" % username):
            return Response({"code": 403, "msg": "登录次数过多 已锁住1分钟"})

        user = User.objects.filter(Q(username=username)|Q(phone=username), password=make_password(password)).first()
        # 判断  user
        usercount = r.get(username)
        if user:
            # 当登录成功时 次数清0
            r.set(username, 0)
            # 生成用户token
            playload = {'exp': int((datetime.datetime.now() + datetime.timedelta(hours=4)).timestamp()),'data': {'uid': user.id}}
            encode_jwt = jwt.encode(playload, '201528', algorithm='HS256')
            encode_str = str(encode_jwt, 'utf-8')
            return Response({"code": 200, "msg": "登录成功", "uid": user.id, "username": user.username,'jwt':encode_str,'type':user.type})
        else:
            if usercount == None:
                return Response({"code": 403, "msg": "用户名或者密码错误"})
            # 登录失败 次数+1
            count = int(usercount.decode('utf-8'))
            if count == 5:
                r.setex("%s-lock" % username, 60, 1)  # 设置登录锁
                return Response({"code": 403, "msg": "登录次数过多 已锁住1分钟"})
            count += 1
            r.set(username, count)
            return Response({"code": 403, "msg": "用户名或者密码错误"})


class Register(APIView):
    def get(self, request):
        # 接受参数
        username = request.GET.get('username', None)
        password = request.GET.get('password', None)
        type = int(request.GET.get('type', 0))
        phone = request.GET.get('phone', None)
        num = int(request.GET.get('num', None))
        code = request.GET.get('code', None)
        # 判断验证码
        if code != r.get('code').decode('utf-8'):
            return Response({"code": 403, "msg": "验证码错误"})
        user = User.objects.filter(username=username).first()
        if user:
            return Response({"code": 403, "msg": "该用户名已存在"})
        # 入库
        try:
            user = User(
                username=username,
                password=make_password(password),
                type=type,
                phone=phone,
                num=num)
            user.save()
        except Exception as e:
            print(e)
            return Response({"code": 403, "msg": "注册失败"})
        r.set(username, 0)  # 新增登录次数
        return Response({"code": 200, "msg": "注册成功", "uid": user.id, "username": user.username})

    def post(self, request):
        # 接受参数
        username = request.POST.get('username', None)
        password = request.POST.get('password', None)

        user = User.objects.filter(username=username).first()
        if user:
            return Response({"code": 403, "msg": "该用户名已存在"})
        # 入库
        user = User(username=username, password=make_password(password))
        user.save()
        return Response({"code": 200, "msg": "注册成功"})


class Update(APIView):
    def get(self, request):
        return Response({"code": 200})

    def post(self, request):
        username = request.POST.get('username', None)
        password = request.POST.get('password', None)
        code = request.POST.get('code', None)
        print(username, password, code)
        if code != r.get('code').decode('utf-8'):
            return Response({"code": 403, "msg": "验证码错误"})

        try:
            user = User.objects.filter(username=username, password=make_password(password)).update(
                password=make_password(password))
        except Exception as e:
            print(e)
            return Response({"code": 403, "msg": "修改失败"})

        return Response({"code": 200, "msg": "修改成功", "username": username})
